package net.flashpunk.masks 
{
	import net.flashpunk.*;
	
	/**
	 * Uses parent's hitbox to determine collision. This class is used
	 * internally by FlashPunk, you don't need to use this class because
	 * this is the default behaviour of Entities without a Mask object.
	 */
	public class Hitbox extends Mask
	{
		/**
		 * Constructor.
		 * @param	width		Width of the hitbox.
		 * @param	height		Height of the hitbox.
		 * @param	x			X offset of the hitbox.
		 * @param	y			Y offset of the hitbox.
		 */
		public function Hitbox(width:uint = 1, height:uint = 1, x:int = 0, y:int = 0) 
		{
			_width = width;
			_height = height;
			_x = x;
			_y = y;
			_check[Mask] = collideMask;
			_check[Hitbox] = collideHitbox;
		}
		
		/** @private Collides against an Entity. */
		private function collideMask(other:Mask):Boolean
		{
			return parent.x + _x + _width > other.parent.x - other.parent.originX
				&& parent.y + _y + _height > other.parent.y - other.parent.originY
				&& parent.x + _x < other.parent.x - other.parent.originX + other.parent.width
				&& parent.y + _y < other.parent.y - other.parent.originY + other.parent.height;
		}
		
		/** @private Collides against a Hitbox. */
		private function collideHitbox(other:Hitbox):Boolean
		{
			return parent.x + _x + _width > other.parent.x + other._x
				&& parent.y + _y + _height > other.parent.y + other._y
				&& parent.x + _x < other.parent.x + other._x + other._width
				&& parent.y + _y < other.parent.y + other._y + other._height;
		}
		
		/**
		 * X offset.
		 */
		public function get x():int { return _x; }
		public function set x(value:int):void
		{
			if (_x == value) return;
			_x = value;
			if (list) list.update();
			else if (parent) update();
		}
		
		/**
		 * Y offset.
		 */
		public function get y():int { return _y; }
		public function set y(value:int):void
		{
			if (_y == value) return;
			_y = value;
			if (list) list.update();
			else if (parent) update();
		}
		
		/**
		 * Width.
		 */
		public function get width():int { return _width; }
		public function set width(value:int):void
		{
			if (_width == value) return;
			_width = value;
			if (list) list.update();
			else if (parent) update();
		}
		
		/**
		 * Height.
		 */
		public function get height():int { return _height; }
		public function set height(value:int):void
		{
			if (_height == value) return;
			_height = value;
			if (list) list.update();
			else if (parent) update();
		}
		
		/** @private Updates the parent's bounds for this mask. */
		override protected function update():void 
		{
			// update entity bounds
			parent.originX = -_x;
			parent.originY = -_y;
			parent.width = _width;
			parent.height = _height;
			
			// update parent list
			if (list) list.update();
		}
		
		// Hitbox information.
		/** @private */ internal var _width:uint;
		/** @private */ internal var _height:uint;
		/** @private */ internal var _x:int;
		/** @private */ internal var _y:int;
	}
}